<template>
  <div v-show="showModel" class="model-content-container">
    <div class="model-main">
      <span v-show="!loading" class="close-btn" @click="closeModel">
          <i class="iconfont icon-quxiao"></i>
      </span>
      <div v-show="loading" id="load">
        <div>G</div>
        <div>N</div>
        <div>I</div>
        <div>D</div>
        <div>A</div>
        <div>O</div>
        <div>L</div>
      </div>
      <div v-show="loading" class="tip">固定带宽3M，获取模型文件较慢，请耐心等待...</div>
      <canvas ref="bjsCanvas" class="bjsCanvas" @click.stop/>
    </div>
  </div>
</template>
<script lang="ts" setup>
import {ref, Ref, nextTick, watch} from "vue";
import {
  Engine,
  Scene,
  ArcRotateCamera,
  Vector3,
  Color4,
  SceneLoader,
  Color3,
} from "@babylonjs/core";
import "@babylonjs/loaders";
import showMessage from "@/components/Message/index"

const props = defineProps({
  modelUrl: {
    type: String,
    default: "",
  },
  showModel: {
    type: Boolean,
    default: false,
  },
});
const bjsCanvas: Ref<HTMLCanvasElement | null> = ref(null);
const loading = ref(false);
let modelEngine: any = ref();
let modelScene: any = ref();

watch(
    () => props.showModel, (newVal) => {
      if (newVal) {
        nextTick(() => {
          if (bjsCanvas.value) {
            const leftModel: Element | null = document.querySelector(".model-main");
            if (leftModel !== null) {
              bjsCanvas.value.width = leftModel.clientWidth;
              bjsCanvas.value.height = leftModel.clientHeight;
            }
            loading.value = true;
            createScene(
                bjsCanvas.value,
                props.modelUrl,
            );
          }
        });
      } else {
        unloadModel();
      }
    }
)

// 新增的卸载模型数据的方法
const unloadModel = () => {
  if (modelEngine.value) {
    modelEngine.value.dispose(); // 清理场景及其所有内容
  }
  if (modelScene.value) {
    modelScene.value.dispose(); // 清理渲染引擎
  }
};

const emit = defineEmits(["closeModel"])

function closeModel() {
  emit("closeModel");
}


const createScene = async (canvas: HTMLCanvasElement, url: string) => {
  const engine: Engine = new Engine(canvas);
  const scene: Scene = new Scene(engine);
  scene.clearColor = new Color4(3 / 255, 3 / 255, 3 / 255, 0.5);
  const camera: ArcRotateCamera = new ArcRotateCamera(
      "Camera",
      Math.PI / 2,
      Math.PI / 2,
      100,
      Vector3.Zero(),
      scene,
  );
  camera.fov = 1.2;
  const setupEnvironment = (scene: Scene) => {
    scene.createDefaultCameraOrLight(true, true, true);
    scene.createDefaultEnvironment({
      createGround: true,
      createSkybox: true,
      enableGroundMirror: true,
      skyboxColor: new Color3(0, 0, 0),
      groundColor: new Color3(0.5, 0.5, 0.5),
    });
  };

  const loadModel = (url: string, scene: Scene): Promise<void> => {
    return new Promise((resolve, reject) => {
      SceneLoader.Append("", url, scene, function (scene) {
        setupEnvironment(scene);
        const model = scene.meshes[0];
        const target = new Vector3(0, 0, 2);
        model.lookAt(target);
        scene.executeWhenReady(() => {
          resolve();
        });
      }, null, (scene, message) => {
        reject(new Error(message));
      });
    });
  };

  loadModel(url, scene).then(() => {
    modelEngine.value = engine;
    modelScene.value = scene;
    loading.value = false;
    engine.runRenderLoop(() => {
      scene.render();
    });
  }).catch(
      (error) => {
        showMessage("模型加载失败", 'success')
        loading.value = false;
        closeModel()
      }
  )
};

</script>
<style lang="scss" scoped>
.bjsCanvas {
  border-radius: 10px;
  outline: none !important;
  cursor: pointer;
}

.model-content-container {
  width: 100%;
  height: 100%;
  position: fixed;
  left: 0;
  top: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1001;
  display: flex;
  align-items: center;
  justify-content: center;

  .model-main {
    width: 80%;
    height: 90%;
    background-color: black;
    border-radius: 10px;
    border: 10px solid #282727;
    position: relative;

    .close-btn {
      position: absolute;
      top: 2%;
      right: 2%;
      width: 40px;
      height: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #282727;
      color: #ffffff;
      font-weight: bold;
      border-radius: 50%;
      cursor: pointer;
      z-index: 1001;

      .icon-quxiao {
        font-size: 20px;
      }
    }
  }
}

.tip {
  position: absolute;
  left: 50%;
  top: 55%;
  transform: translateX(-50%);
  color: #6d6e78;
  font-size: 15px;
  font-family: "宋体", serif;
}

#load {
  position: absolute;
  width: 600px;
  height: 36px;
  left: 50%;
  top: 50%;
  transform: translateY(-50%);
  margin-left: -300px;
  overflow: visible;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  cursor: default;
}

#load div {
  position: absolute;
  width: 20px;
  height: 36px;
  opacity: 0;
  font-family: Helvetica, Arial, sans-serif;
  animation: move 2s linear infinite;
  -o-animation: move 2s linear infinite;
  -moz-animation: move 2s linear infinite;
  -webkit-animation: move 2s linear infinite;
  transform: rotate(180deg);
  -o-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  color: #35C4F0;
}

#load div:nth-child(2) {
  animation-delay: 0.2s;
  -o-animation-delay: 0.2s;
  -moz-animation-delay: 0.2s;
  -webkit-animation-delay: 0.2s;
}

#load div:nth-child(3) {
  animation-delay: 0.4s;
  -o-animation-delay: 0.4s;
  -webkit-animation-delay: 0.4s;
  -webkit-animation-delay: 0.4s;
}

#load div:nth-child(4) {
  animation-delay: 0.6s;
  -o-animation-delay: 0.6s;
  -moz-animation-delay: 0.6s;
  -webkit-animation-delay: 0.6s;
}

#load div:nth-child(5) {
  animation-delay: 0.8s;
  -o-animation-delay: 0.8s;
  -moz-animation-delay: 0.8s;
  -webkit-animation-delay: 0.8s;
}

#load div:nth-child(6) {
  animation-delay: 1s;
  -o-animation-delay: 1s;
  -moz-animation-delay: 1s;
  -webkit-animation-delay: 1s;
}

#load div:nth-child(7) {
  animation-delay: 1.2s;
  -o-animation-delay: 1.2s;
  -moz-animation-delay: 1.2s;
  -webkit-animation-delay: 1.2s;
}

@keyframes move {
  0% {
    left: 0;
    opacity: 0;
  }
  35% {
    left: 41%;
    -moz-transform: rotate(0deg);
    -webkit-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  65% {
    left: 59%;
    -moz-transform: rotate(0deg);
    -webkit-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  100% {
    left: 100%;
    -moz-transform: rotate(-180deg);
    -webkit-transform: rotate(-180deg);
    -o-transform: rotate(-180deg);
    transform: rotate(-180deg);
    opacity: 0;
  }
}

@-moz-keyframes move {
  0% {
    left: 0;
    opacity: 0;
  }
  35% {
    left: 41%;
    -moz-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  65% {
    left: 59%;
    -moz-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  100% {
    left: 100%;
    -moz-transform: rotate(-180deg);
    transform: rotate(-180deg);
    opacity: 0;
  }
}

@-webkit-keyframes move {
  0% {
    left: 0;
    opacity: 0;
  }
  35% {
    left: 41%;
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  65% {
    left: 59%;
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  100% {
    left: 100%;
    -webkit-transform: rotate(-180deg);
    transform: rotate(-180deg);
    opacity: 0;
  }
}

@-o-keyframes move {
  0% {
    left: 0;
    opacity: 0;
  }
  35% {
    left: 41%;
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  65% {
    left: 59%;
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
    opacity: 1;
  }
  100% {
    left: 100%;
    -o-transform: rotate(-180deg);
    transform: rotate(-180deg);
    opacity: 0;
  }
}
</style>
